package com.fashiontextile.auth.controller;

import com.anji.captcha.service.CaptchaService;
import com.fashiontextile.auth.entity.LoginBody;
import com.fashiontextile.auth.entity.RegisterBody;
import com.fashiontextile.auth.service.TokenService;
import com.fashiontextile.common.constant.AppConstants;
import com.fashiontextile.common.constant.TokenConstants;
import com.fashiontextile.common.entity.R;
import com.fashiontextile.common.exception.AuthenticationException;
import com.fashiontextile.common.utils.IdUtils;
import com.fashiontextile.user.entity.Role;
import com.fashiontextile.user.entity.User;
import com.fashiontextile.user.feign.UserClient;
import com.nimbusds.jose.JOSEException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author brooke_zb
 */
@Slf4j
@RestController
@AllArgsConstructor
public class TokenController {
    private TokenService tokenService;
    private CaptchaService captchaService;
    private UserClient userClient;
    private IdUtils idUtils;

    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    @PostMapping("/token")
    public R<?> login(@RequestBody LoginBody body, HttpServletResponse response) throws AuthenticationException {

        // 校验验证码
//        if (!captchaService.verification(body.getCaptcha()).isSuccess()) {
//            throw new AuthenticationException("验证码校验失败");
//        }

        // 检验登录信息
        if (body.getUsername().isEmpty() || body.getPassword().isEmpty()) {
            throw new AuthenticationException("用户名或密码不在合法范围");
        }

        // 获取登录用户信息
        R<User> result = userClient.getUserByUsername(body.getUsername());
        if (!result.isSuccess()) {
            throw new AuthenticationException(result.getMsg());
        }

        // 校验密码
        if (!encoder.matches(body.getPassword(), result.getData().getPassword())) {
            throw new AuthenticationException("密码错误");
        }

        // 校验用户状态
        if (!result.getData().isEnable()) {
            throw new AuthenticationException("您的账户已停用，请联系管理员");
        }

        // 返回jwt
        try {
            Map<String, Object> jwt = tokenService.createToken(result.getData());
            Cookie cookie = new Cookie(TokenConstants.TOKEN_HEADER, (String) jwt.get("accessToken"));
            cookie.setMaxAge((int) TimeUnit.MINUTES.toSeconds(TokenConstants.EXPIRATION));
            cookie.setPath("/");
            response.addCookie(cookie);
            return R.success(jwt);
        } catch (JOSEException e) {
            log.error("Error when create jwt token", e);
            throw new AuthenticationException("创建令牌失败，请稍后重试");
        }
    }

    @DeleteMapping("/token")
    public R<?> logout(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        // 获取jwt
        String jwt = request.getHeader(TokenConstants.TOKEN_HEADER);
        if (jwt == null || jwt.isEmpty()) {
            throw new AuthenticationException("当前未登录");
        }

        try {
            tokenService.deleteToken(jwt);
            Cookie removeCookie = new Cookie(TokenConstants.TOKEN_HEADER, "");
            removeCookie.setPath("/");
            removeCookie.setMaxAge(0);
            response.addCookie(removeCookie);
        } catch (JOSEException | ParseException e) {
            throw new AuthenticationException("令牌不合法");
        }

        return R.success("成功退出登录");
    }

    @PostMapping("/register")
    public R<?> register(@RequestBody RegisterBody registerBody) {
        // 校验验证码
//        if (!captchaService.verification(registerBody.getCaptcha()).isSuccess()) {
//            throw new AuthenticationException("验证码校验失败");
//        }

        // 验证用户名是否已经存在
        R<User> resultUsername = userClient.getUserByUsername(registerBody.getUsername());
        if (resultUsername.isSuccess()) {
            throw new AuthenticationException("用户名已存在");
        }

        // 验证邮箱是否已经存在
        R<User> resultEmail = userClient.getUserByEmail(registerBody.getEmail());
        if (resultEmail.isSuccess()) {
            throw new AuthenticationException("邮箱已被注册");
        }

        R<Role> roleResult = userClient.getRoleByName(AppConstants.ROLE_USER);
        if (!roleResult.isSuccess()) {
            throw new AuthenticationException("注册失败，请联系管理员");
        }

        // 注册用户
        User user = new User();
        user.setUid(idUtils.nextId());
        user.setUsername(registerBody.getUsername());
        user.setPassword(encoder.encode(registerBody.getPassword()));
        user.setRole(roleResult.getData());
        user.setEmail(registerBody.getEmail());
        user.setRegtime(new Date());
        return userClient.insertUser(user);
    }

}
